//
//  GZSQLModelResolver.m
//  GZSQLModelTool_Example
//
//  Created by Guo Rui on 2018/1/25.
//  Copyright © 2018年 GR. All rights reserved.
//

#import "GZSQLModelResolver.h"
#import <objc/runtime.h>
#import "GZSQLModelProtocol.h"

@implementation GZSQLModelResolver

+ (NSString *)tableName:(Class)cls
{
    NSString *clsName = NSStringFromClass(cls);
    return [@"t_" stringByAppendingString:clsName];
}

+ (NSString *)tmpTableName:(Class)cls
{
    NSString *tableName = [self tableName:cls];
    return [tableName stringByAppendingString:@"Tmp"];
}

+ (NSDictionary *)classIvarNameTypeDict:(Class)cls
{
    NSMutableDictionary *ivarNameTypeDictM = [NSMutableDictionary dictionary];
    
    unsigned int count = 0;
    Ivar *ivars = class_copyIvarList(cls, &count);
    
    // 向类获取忽略的字段
    NSArray *ignoreKeys = nil;
    if ([cls respondsToSelector:@selector(ignoreKeys)]) {
        ignoreKeys = [cls ignoreKeys];
    }
    
    for (int i = 0; i < count; i++) {
        Ivar ivar = ivars[i];
        
        // 1. 获取变量名
        NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)];
        if ([ivarName hasPrefix:@"_"]) {
            ivarName = [ivarName substringFromIndex:1];
        }
        
        if ([ignoreKeys containsObject:ivarName]) {
            // 过滤忽略的字段
            continue;
        }
        
        // 2. 获取变量的类型
        NSString *typeName = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
        
        // typeName = @\"NSString\"
        typeName = [typeName stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"@\""]];
        
        [ivarNameTypeDictM setObject:typeName forKey:ivarName];
    }
    
    return ivarNameTypeDictM.copy;
}

+ (NSDictionary *)classIvarNameSqliteTypeDict:(Class)cls
{
    NSDictionary *ivarNameTypeDict = [self classIvarNameTypeDict:cls];
    NSMutableDictionary *ivarNameSqliteTypeDictM = [NSMutableDictionary dictionaryWithCapacity:0];
    
    [ivarNameTypeDict enumerateKeysAndObjectsUsingBlock:^(NSString  *_Nonnull ivarName, NSString * _Nonnull typeName, BOOL * _Nonnull stop) {
        NSString *sqliteTypeName = self.ocTypeToSqliteTypeDic[typeName];
        [ivarNameSqliteTypeDictM setObject:sqliteTypeName forKey:ivarName];
    }];
    
    return ivarNameSqliteTypeDictM.copy;
}

+ (NSString *)columnName4TypeStr:(Class)cls
{
    NSDictionary *ivarTypeDict = [GZSQLModelResolver classIvarNameSqliteTypeDict:cls];
    NSMutableArray *ivarTypes = [NSMutableArray arrayWithCapacity:0];
    
    [ivarTypeDict enumerateKeysAndObjectsUsingBlock:^(NSString *_Nonnull ivarName, NSString *_Nonnull type, BOOL * _Nonnull stop) {
        
        NSString *pairStr = [NSString stringWithFormat:@"%@ %@", ivarName, type];
        [ivarTypes addObject:pairStr];
    }];
    NSString *ivarTypeStr = [ivarTypes componentsJoinedByString:@","];
    
    return ivarTypeStr;
}

+ (NSArray *)classSortedIvarNames:(Class)cls
{
    NSDictionary *dict = [self classIvarNameTypeDict:cls];
    NSArray *ivarNames = dict.allKeys;
    
    if (ivarNames.count == 0) {
        return nil;
    }
    
    return [ivarNames sortedArrayUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
        return [obj1 compare:obj2];
    }];
}

#pragma mark - Private
+ (NSDictionary *)ocTypeToSqliteTypeDic {
    return @{
             @"d": @"real", // double
             @"f": @"real", // float
             
             @"i": @"integer",  // int
             @"q": @"integer", // long
             @"Q": @"integer", // long long
             @"B": @"integer", // bool
             
             @"NSData": @"blob",
             @"NSDictionary": @"text",
             @"NSMutableDictionary": @"text",
             @"NSArray": @"text",
             @"NSMutableArray": @"text",
             
             @"NSString": @"text"
             };
    
}


+ (NSString *)modelPrimaryKey:(Class)cls
{
    if (![cls respondsToSelector:@selector(primaryKey)]) {
        NSLog(@"必须要实现+ (NSString *)primaryKey;这个方法, 来告诉我主键信息");
        return nil;
    }
    
    NSString *primaryKey = [cls primaryKey];
    return primaryKey;
}

@end
